package com.spc.car.data.config;


import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ObjectUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

public class AbstractDataSourceEnvironmentAware implements EnvironmentAware {
    private static final Logger logger = LoggerFactory.getLogger(AbstractDataSourceEnvironmentAware.class);
    protected Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public DataSource dataSource(DruidPoolProperties dataSourceProperties) throws SQLException {
        if (StringUtils.isEmpty(dataSourceProperties.getUrl())) {
            logger.error("数据库连接池配置错误!"
                    + " 请检查Spring配置文件，目前的配置有："
                    + Arrays.toString(environment.getActiveProfiles()));
            throw new ApplicationContextException(
                    "数据库连接池配置错误");
        }
        return this.setCommonDataSourceProperties(dataSourceProperties);
    }

    //mybatis
    public SqlSessionFactory sqlSessionFactory( DataSource dataSource, String locationPattern) throws Exception {
        final SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);

        //bean.setPlugins(new Interceptor[]{new ResultSetInterceptor(), new CameHumpInterceptor()});

        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(locationPattern));

        return bean.getObject();
    }

    //mybatis-plus
    public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean(DataSource dataSource,
                                                                     MybatisPlusProperties mybatisPlusProperties,
                                                                     List<Interceptor> interceptors,
                                                                     DatabaseIdProvider databaseIdProvider) throws Exception {

        MybatisSqlSessionFactoryBean mybatisPlus = new MybatisSqlSessionFactoryBean();

        mybatisPlus.setDataSource(dataSource);
        mybatisPlus.setVfs(SpringBootVFS.class);
        if (org.springframework.util.StringUtils.hasText(mybatisPlusProperties.getConfigLocation())) {
            mybatisPlus.setConfigLocation(new DefaultResourceLoader().getResource(mybatisPlusProperties.getConfigLocation()));
        }

        mybatisPlus.setConfiguration(mybatisPlusProperties.getConfiguration());

        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        if (!ObjectUtils.isEmpty(interceptors)) {
            interceptors.add(paginationInterceptor);
        } else {
            interceptors = Arrays.asList(paginationInterceptor);
        }
        mybatisPlus.setPlugins(interceptors.toArray(new Interceptor[]{}));

        Interceptor[] is = new Interceptor[]{paginationInterceptor};
        mybatisPlus.setPlugins(is);

        // MP 全局配置，更多内容进入类看注释
        GlobalConfig globalConfig = new GlobalConfig();
        GlobalConfig.DbConfig dbConfig= new GlobalConfig.DbConfig();

        //globalConfig.setDbType(DBType.SQLSERVER.getDb());
        // ID 策略 AUTO->`0`("数据库ID自增") INPUT->`1`(用户输入ID") ID_WORKER->`2`("全局唯一ID") UUID->`3`("全局唯一ID")
        dbConfig.setIdType(IdType.AUTO);
        globalConfig.setDbConfig(dbConfig);
        //globalConfig.setFieldStrategy(FieldStrategy.NOT_EMPTY.getKey());
        mybatisPlus.setGlobalConfig(globalConfig);

        MybatisConfiguration mc = new MybatisConfiguration();
        mc.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        //mapUnderscoreToCamelCase：是否启用下划线与驼峰式命名规则的映射（如first_name => firstName）
        mc.setMapUnderscoreToCamelCase(true);
        mybatisPlus.setConfiguration(mc);
        if (databaseIdProvider != null) {
            mybatisPlus.setDatabaseIdProvider(databaseIdProvider);
        }
        if (org.springframework.util.StringUtils.hasLength(mybatisPlusProperties.getTypeAliasesPackage())) {
            mybatisPlus.setTypeAliasesPackage(mybatisPlusProperties.getTypeAliasesPackage());
        }
        if (org.springframework.util.StringUtils.hasLength(mybatisPlusProperties.getTypeHandlersPackage())) {
            mybatisPlus.setTypeHandlersPackage(mybatisPlusProperties.getTypeHandlersPackage());
        }
        if (!ObjectUtils.isEmpty(mybatisPlusProperties.resolveMapperLocations())) {
            mybatisPlus.setMapperLocations(mybatisPlusProperties.resolveMapperLocations());
        }

        return mybatisPlus;
    }


    protected DruidDataSource setCommonDataSourceProperties(DruidPoolProperties dataSourceProperties) throws SQLException {
        final DruidDataSource druidDataSource = new DruidDataSource();

        druidDataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        druidDataSource.setUrl(dataSourceProperties.getUrl());
        druidDataSource.setUsername(dataSourceProperties.getUsername());
        druidDataSource.setPassword(dataSourceProperties.getPassword());
        druidDataSource.setInitialSize(dataSourceProperties.getInitialSize());
        druidDataSource.setMinIdle(dataSourceProperties.getMinIdle());
        druidDataSource.setMaxActive(dataSourceProperties.getMaxActive());
        druidDataSource.setMaxWait(dataSourceProperties.getMaxWait());
        druidDataSource.setTimeBetweenEvictionRunsMillis(dataSourceProperties.getTimeBetweenEvictionRunsMillis());
        druidDataSource.setMinEvictableIdleTimeMillis(dataSourceProperties.getMinEvictableIdleTimeMillis());
        druidDataSource.setValidationQuery(dataSourceProperties.getValidationQuery());
        druidDataSource.setTestWhileIdle(dataSourceProperties.isTestWhileIdle());
        druidDataSource.setTestOnBorrow(dataSourceProperties.isTestOnBorrow());
        druidDataSource.setTestOnReturn(dataSourceProperties.isTestOnReturn());
        druidDataSource.setPoolPreparedStatements(dataSourceProperties.isPoolPreparedStatements());
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(dataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize());
        if (StringUtils.isNotBlank(dataSourceProperties.getFilters())) {
            druidDataSource.setFilters(dataSourceProperties.getFilters());
        } else {
            druidDataSource.setFilters("stat");
        }
        /*if (StringUtils.isNotBlank(dataSourceProperties.getConnectionProperties())) {
            Properties connectProperties = new Properties();
            try {
                connectProperties.load(new StringReader(dataSourceProperties.getConnectionProperties()));
                druidDataSource.setConnectProperties(connectProperties);
            } catch (Exception e) {

            }
        }*/
        if (null != dataSourceProperties.getConnectionProperties()) {
            druidDataSource.setConnectProperties(dataSourceProperties.getConnectionProperties());
        }
        druidDataSource.setUseGlobalDataSourceStat(dataSourceProperties.isUseGlobalDataSourceStat());
        druidDataSource.setQueryTimeout(10);
        druidDataSource.setTransactionQueryTimeout(10);
        return druidDataSource;
    }
}
